package tm.testing;



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ImageIcon;

import org.lex.game.StrategicHandlerDefaults;
import org.lex.input.StrategicHandler;
import org.lex.input.StrategicCameraEffects;
import org.lex.input.effects.HeightMap;
import org.lex.input.mouse.Cursor;
import org.lex.input.mouse.MouseBindingManager;
import org.lex.input.mouse.MouseManager;
import org.lex.input.mouse.component.CombinedMouse;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.entity.Entity;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.MouseInputListener;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.intersection.PickResults;
import com.jme.intersection.TrianglePickResults;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Ray;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Point;
import com.jme.scene.Spatial;
import com.jme.scene.TriMesh;
import com.jme.scene.Spatial.CullHint;
import com.jme.scene.Spatial.LightCombineMode;
import com.jme.scene.Spatial.TextureCombineMode;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Quad;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.BresenhamTerrainPicker;
import com.jmex.terrain.util.ImageBasedHeightMap;

public class TrafficTest extends SimpleGame implements MouseInputListener {
	
	
	
	public MouseInputState mouseInputState;
	
	//SOME COLOR OVERLAYSTATES
	private ColorOverlay redColorOL;
	
	private KeyBindingManager keyboard;
	private MouseBindingManager mouseBinding;
	private StrategicHandler strategicHandler;
	private FirstPersonHandler firstPersonHandler;
	private StrategicCameraEffects camEffects;
	private TerrainPage terrain;
	
	private String defaultCursor = "defaultCursor";
	private String attackCursor = "attackCursor";
	private String selectCursor = "selectCursor";
	private String[] cursors = {defaultCursor, attackCursor, selectCursor};
	private int currentCursorIndex;
	
	private String cmdNextCursor = "nextCursor";
	private String cmdChangeLocation = "changeLocation";
	private String cmdToggleHeightOffset = "toggleHeightOffset";
	private String cmdFlyToOrigin = "flyToOrigin";
	
	private String mbLeftClick = "leftClick";
	
	
	private float modifiedHeight = 50;
	
	private BresenhamTerrainPicker picker;
	
	private Quad minimap;
	private float minimapWidth = 200;
	private float minimapHeight = 200;
	private Vector2f mapLocation = new Vector2f();
	
	private TerrainPage page;
	private Node terrainNode;
	private float farPlane = 10000.0f; //used to calculate fog
	
	private Sphere ball;
	
	//IMPORTANT VALUES NOW SET STATIC!------
	private MapGrid mapGrid;
	private int gridSize = 80;
	private int gridElements = 64;
	//--------------------------------------
	
	private ArrayList<Vehicle> vehicleList;
	private Node map;
	private Node vehicles;
	
	
	private Road buildRoad;
	
	private Vehicle van;
	
	public static void main(String[] args) {
		Logger.getLogger("").setLevel(Level.WARNING);
		TrafficTest game = new TrafficTest();
		game.setConfigShowMode(ConfigShowMode.AlwaysShow);
		game.start();
	}
	
	@Override
	protected void simpleInitGame() {
		//initialize entity list
		vehicleList = new ArrayList<Vehicle>();
		vehicles = new Node();
		rootNode.attachChild(vehicles);
		
		
		//initialize cull state
		CullState cs = display.getRenderer().createCullState();
		cs.setCullFace(CullState.Face.Back);
		cs.setEnabled(true);
		rootNode.setRenderState(cs);
		
		//do some stuff
		setupTerrain();
		setupLightAndFog();
		//setupControls();
		setupInput();
		setupMisc();
		
		//THIS IS ONLY FOR TESTING; INIT SOME STUFF...
		setupTestStuff();
		
	}
	
	
	private void setupTestStuff() {
		mouseInputState.setTRACK_INSTALLER(true);
		mouseInputState.setVEHICLE_SELECTOR(false);		
		
		
		buildRoad = new Road("buildRoad", mapGrid);
		
		
		Road road = new Road("road", mapGrid);
		road.addField(new Coordinate(31,28));
		road.addField(new Coordinate(31,29));
		road.addField(new Coordinate(31,31));
		road.addField(new Coordinate(31,32));
		road.addField(new Coordinate(32,32));
		road.addField(new Coordinate(33,32));
		road.addField(new Coordinate(34,32));
		road.addField(new Coordinate(35,32));
		road.addField(new Coordinate(35,33));
		road.addField(new Coordinate(35,34));
		road.addField(new Coordinate(36,34));
		road.addField(new Coordinate(37,34));
		road.addField(new Coordinate(38,34));
		road.addField(new Coordinate(38,33));
		road.addField(new Coordinate(38,32));
		road.addField(new Coordinate(38,31));
		road.addField(new Coordinate(38,30));
		road.addField(new Coordinate(37,30));
		road.addField(new Coordinate(36,30));
		road.addField(new Coordinate(35,30));
		road.addField(new Coordinate(34,30));
		road.addField(new Coordinate(33,30));
		road.addField(new Coordinate(32,30));
		road.addField(new Coordinate(31,30));
		road.addField(new Coordinate(30,30));
		road.addField(new Coordinate(33,31));
		road.updateCurve();
		road.computeSpatials();
		road.showGeometry();
		
		
		
		  
		BusRoute busroute = new BusRoute("BusRoute", mapGrid, road);
		busroute.addSegment(new Coordinate(32,32), Road.RIGHT);
		busroute.addSegment(new Coordinate(33,32), Road.RIGHT);
		busroute.addSegment(new Coordinate(34,32), Road.RIGHT);
		busroute.addSegment(new Coordinate(35,32), Road.RIGHT);
		busroute.addSegment(new Coordinate(35,33), Road.RIGHT);
		busroute.addSegment(new Coordinate(35,34), Road.RIGHT);
		busroute.buildCurve();
		//only for debug
		rootNode.attachChild(busroute.getCurve());
		  
		  
		// Load first bus model test object:
	      URL model=Road.class.getClassLoader().getResource("data/models/bus.obj");

	      // Create something to convert .obj format to .jme
	      FormatConverter converter=new ObjToJme();
	      // Point the converter to where it will find the .mtl file from
	      converter.setProperty("mtllib",model);

	      // This byte array will hold my .jme file
	      ByteArrayOutputStream BO=new ByteArrayOutputStream();

	      // Use the format converter to convert .obj to .jme
	      Spatial busmodel = null;
	     try {
	    	  converter.convert(model.openStream(), BO);
	    	  busmodel = (Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
		      busmodel.setName("ECKIBUS");
		      busmodel.setModelBound(new BoundingSphere());
		      busmodel.updateModelBound();
		      busmodel.setLocalScale(12);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		
		
		van = new Vehicle("VAN", busroute.getCurve(), busmodel);
		//van.setMotionState(Vehicle.DRIVING);
		vehicleList.add(van);
		vehicles.attachChild(van.getSpatial());
		
		
		NonResidentialBuilding nrb = new NonResidentialBuilding("office1");
		nrb.loadObjModel("data/models/office_building.obj", 83);
		try {
			mapGrid.getGridElement(32, 33).addStructure(nrb);
			nrb.setPosition(new Coordinate(32,33), mapGrid);
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		SuburbanTrain sbahn = new SuburbanTrain("SBAHN", busroute.getCurve(), SuburbanTrain.loadXMLModel("data/models/spermanzug.xml"));
		sbahn.setMotionState(SuburbanTrain.DRIVING);
		vehicleList.add(sbahn);
		vehicles.attachChild(sbahn.getSpatial());
		
		
		
        // Set up a ball that will show our pick location.
        ball = new Sphere("ball", 32, 32, 10);
        ball.setModelBound(new BoundingBox());
        // Turn off texturing.
        ball.setTextureCombineMode(TextureCombineMode.Off);
        ball.updateModelBound();
        rootNode.attachChild(ball);
        

	}
	
	public void setupTerrain() {
		//Setup MapGrid for Game:
		map = new Node();
		rootNode.attachChild(map);
		mapGrid = new MapGrid(gridSize, gridElements, map);
		
		terrainNode = new Node();
		ImageIcon image = new ImageIcon(TestOne.class.getClassLoader().getResource("data/textures/testterrain.png"));
		  
		  
		ImageBasedHeightMap heightMap = new ImageBasedHeightMap(image.getImage());
		Vector3f terrainScale = new Vector3f(10,1,10);
		heightMap.setHeightScale( 0.001f);
		page = new TerrainPage("Terrain", 33, heightMap.getSize(), terrainScale,
				  					heightMap.getHeightMap());
		
		page.setDetailTexture(1, gridElements);
		terrainNode.attachChild(page);
		    
		Texture testgrass = TextureManager.loadTexture(TestOne.class.getClassLoader().
		          getResource(
		                  "data/textures/nicegrass.jpg"),
		                                                      Texture.MinificationFilter.Trilinear,
		                                                      Texture.MagnificationFilter.Bilinear);
		testgrass.setScale(new Vector3f(90.0f,90.0f,1.0f));
		  
		TextureState ts = display.getRenderer().createTextureState();
		ts.setEnabled(true);
		
		    
		ts.setTexture(testgrass, 0);
		testgrass.setWrap(Texture.WrapMode.Repeat);
		  
		
		Texture t2 = TextureManager.loadTexture(TestOne.class.getClassLoader().
		                                          getResource(
		     "data/textures/Untitled.png"),
		                                          Texture.MinificationFilter.Trilinear,
		                                          Texture.MagnificationFilter.Bilinear);
		ts.setTexture(t2, 1);
		t2.setWrap(Texture.WrapMode.Repeat);
			
		testgrass.setApply(Texture.ApplyMode.Combine);
		testgrass.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
		testgrass.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
		testgrass.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
		testgrass.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
		testgrass.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
		
		
		t2.setApply(Texture.ApplyMode.Combine);
		t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
		t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
		t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
		t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
		t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
		terrainNode.setRenderState(ts);
		rootNode.attachChild(terrainNode);
		
		
		//Initialize terrain picker
		picker = new BresenhamTerrainPicker(page);
	}
	
	public void setupLightAndFog() {
		//Setup Light 1
		DirectionalLight dl = new DirectionalLight();
		dl.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
		dl.setDirection(new Vector3f(1, -0.5f, 1));
		dl.setEnabled(true);
		lightState.attach(dl);
				
		//Setup Light 2
		DirectionalLight dr = new DirectionalLight();
		dr.setEnabled(true);
		dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
		dr.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
		dr.setDirection(new Vector3f(0.5f, -0.5f, 0).normalizeLocal());
		lightState.attach(dr);

		//Setup Fog
		FogState fogState = display.getRenderer().createFogState();
		fogState.setDensity(1.0f);
		fogState.setEnabled(true);
		fogState.setColor(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
		fogState.setEnd(farPlane);
		fogState.setStart(farPlane / 10.0f);
		fogState.setDensityFunction(FogState.DensityFunction.Linear);
		fogState.setQuality(FogState.Quality.PerVertex);
		terrainNode.setRenderState(fogState);
	}
	
	
    protected void cameraPerspective() {
        cam.setFrustumPerspective( 60.0f, (float) display.getWidth()
                / (float) display.getHeight(), 1, 3500 );
        cam.setParallelProjection( false );
        cam.update();
    }


	public void setupInput() {		
		
		mouseInputState = new MouseInputState();
		
		
		HeightMap heightMap = new HeightMap() {
			public float getHeightAt(Vector3f location) {
				float height = 250;
				if (Float.isNaN(height)) height = 0;
				return height;
			}
		};
		
		MouseManager mouseManager = new MouseManager(CombinedMouse.get());
		
		statNode.attachChild(mouseManager.getMouse().getMouseSpatial());
		mouseManager.setMousePosition(
				display.getWidth()/2, display.getHeight()/2);
		
		mouseManager.setCursor(defaultCursor,
				"org/lex/cursors/goldenarrow_v2/default.cursor");
		mouseManager.setCursor(attackCursor,
				"org/lex/cursors/goldenarrow_v2/spinning.cursor");
		mouseManager.setCursor(selectCursor,
				"org/lex/cursors/goldenarrow_select/default.cursor");


		
		strategicHandler = new StrategicHandler(
				cam, mouseManager, heightMap);
		input = strategicHandler;
		
		
		HashMap<String,String> cursors = new HashMap<String,String>();
		cursors.put(StrategicHandler.CURSOR_ROTATE,
				"org/lex/cursors/goldenarrow_rotate/default.cursor");
		cursors.put(StrategicHandler.CURSOR_SCROLL_UP,
				"org/lex/cursors/goldenscroll_up/default.cursor");
		cursors.put(StrategicHandler.CURSOR_SCROLL_UPLEFT,
		"org/lex/cursors/goldenscroll_upleft/default.cursor");
		strategicHandler.updateCursors(cursors);

		mouseManager.registerWithInputHandler(strategicHandler);
		mouseManager.addListener(this);
		statNode.attachChild(mouseManager.getMouse().getMouseSpatial());
		
		
		
		
		//Kind of a weird workaround code here:
		mouseManager.setNativeMousePreferred(true);
		mouseManager.getMouse().setCursorVisible(true);
		update(0);
		mouseManager.setNativeMousePreferred(false);
		
		
		
		
		/*
		strategicHandler = new StrategicHandler(
				cam, mouseManager, heightMap);
		camEffects = new StrategicCameraEffects(strategicHandler);
		strategicHandler.setCameraEffects(camEffects);
		input.addToAttachedHandlers(strategicHandler);
		
		
		strategicHandler.updateProperties(
				StrategicHandlerDefaults.getCustomConfig());
		
		*/
		
		
		/*
		// this is how to set cursors via setters
			strategicHandler.getMouseManager().setCursor(
				StrategicHandler.CURSOR_ROTATE,
				Cursor.load(this.getClass().getClassLoader().getResource(
					"org/lex/cursors/goldenarrow.car"),
				"spinning.cursor"));
		*/
		
	}
	
	public void setupMisc() {
		
		redColorOL = new ColorOverlay(ColorRGBA.red, display.getRenderer(), true);
		
		
		
		/**
		minimap = new Quad("myQuad", minimapWidth, minimapHeight);
		minimap.setLocalTranslation(minimapWidth/2 + 5, minimapHeight/2 + 20, 0);
        minimap.setRenderQueueMode(Renderer.QUEUE_ORTHO);
        minimap.setCullHint(CullHint.Never);
        minimap.setLightCombineMode(LightCombineMode.Off);
        minimap.setTextureCombineMode(Spatial.TextureCombineMode.Off);
        minimap.setDefaultColor(new ColorRGBA(ColorRGBA.white));
        minimap.getDefaultColor().a = 0.5f;
        BlendState as = display.getRenderer().createBlendState();
        as.setBlendEnabled(true);
		as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		as.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		as.setTestEnabled(true);
		as.setTestFunction(BlendState.TestFunction.GreaterThan);
		as.setEnabled(true);
		minimap.setRenderState(as);
        statNode.attachChild(minimap);
        */
	}
	
	@Override
	protected void simpleUpdate() {
		if (strategicHandler.isEnabled()) {
			/*
			 * Remember to update your cursor every frame. You will want to
			 * do this, because after you do mouse picking you can choose
			 * differet cursors based on the result of the mouse pick.
			 * 
			 * Example: you can set a different cursor when the mouse is
			 * hovering over an enemy vs the default cursor.
			*/
			strategicHandler.useCursor(cursors[currentCursorIndex]);
		}	
		
		//UPDATE VEHICLE LIST-----------------------------------------
		Iterator<Vehicle> enIt = vehicleList.iterator();
		while(enIt.hasNext()) {
			enIt.next().update();
		}
		//------------------------------------------------------------
		
		
		
	}
	
	@Override
	protected void updateInput() {
		super.updateInput();
		
	}
	

	private void processPick(int x, int y) {
		System.out.println("PICK!");
    		
    	//mouseState.setMousePosition(new Coordinate(mouse_x, mouse_y));
    		
    	Vector2f screenPos = new Vector2f();
    	//Get the position that the mouse is pointing to
		screenPos.set(x, y);
		// Get the world location of that X,Y value
		Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
		// Create a ray starting from the camera, and going in the direction
        // of the mouse's location
        final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
                .subtractLocal(cam.getLocation()));
        mouseRay.getDirection().normalizeLocal();
        TrianglePickResults results = new TrianglePickResults();
        results.clear();
        results.setCheckDistance(true);
        vehicles.calculatePick(mouseRay,results);
        
    	if(results.getNumber() > 0) {
    		System.out.println("VORHER: "+results.getNumber()+" AHA: "+results.getPickData(0).getTargetMesh().getName());
    	
	    	Vehicle tmp = Vehicle.getVehicleBySpatialName(vehicleList, results.getPickData(0).getTargetMesh().getName());
	    	System.out.println(tmp.getId());
	    	if(tmp.getMotionState()==Vehicle.DRIVING) {
	    		tmp.setMotionState(Vehicle.IDLE);
	    		redColorOL.addSpatial(tmp.getSpatial());
	    	} else if (tmp.getMotionState()==Vehicle.IDLE) {
	    		tmp.setMotionState(Vehicle.DRIVING);
	    		redColorOL.removeSpatial(tmp.getSpatial());
	    	}
    	}
    	
	}
	
	private void mouseProcessNewRoadElementMode(int x, int y) {
		
    	Vector2f screenPos = new Vector2f();
    	//Get the position that the mouse is pointing to
		screenPos.set(x, y);
		// Get the world location of that X,Y value
		Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
		// Create a ray starting from the camera, and going in the direction
        // of the mouse's location
        final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
                .subtractLocal(cam.getLocation()));
        mouseRay.getDirection().normalizeLocal();
        //Calculate terrain intersection and set ball translation
        picker.getTerrainIntersection(mouseRay, ball.getLocalTranslation());
        Coordinate mapCoord = mapGrid.getGridIndex(ball.getWorldTranslation());
        try {
			GridElement ge = mapGrid.getGridElement(mapCoord.getX(), mapCoord.getY());
			if(!ge.isEmpty()) {
	    		redColorOL.addSpatial(ball);
			} else {
				if(redColorOL.isContained(ball)) {
					redColorOL.removeSpatial(ball);
				}
				
				
			}
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        
        
        
        //System.out.println("VEKTOR IST: V("+ball.getLocalTranslation().getX()+"|"+ball.getLocalTranslation().getY()+"|"+ball.getLocalTranslation().getZ()+")");
        System.out.println(mapGrid.getGridIndex(ball.getWorldTranslation()).getX()+" UND "+mapGrid.getGridIndex(ball.getWorldTranslation()).getY());
	}
	
	private void mouseNewRoadElement(int x, int y) {
    	Vector2f screenPos = new Vector2f();
    	//Get the position that the mouse is pointing to
		screenPos.set(x, y);
		// Get the world location of that X,Y value
		Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
		// Create a ray starting from the camera, and going in the direction
        // of the mouse's location
        final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
                .subtractLocal(cam.getLocation()));
        mouseRay.getDirection().normalizeLocal();
        //Calculate terrain intersection and set ball translation
        picker.getTerrainIntersection(mouseRay, ball.getLocalTranslation());
        Coordinate mapCoord = mapGrid.getGridIndex(ball.getWorldTranslation());
        try {
			GridElement ge = mapGrid.getGridElement(mapCoord.getX(), mapCoord.getY());
			if(!ge.isEmpty()) {
	    		redColorOL.addSpatial(ball);
			} else {
				//Check if the surrounding 4 fields contain any other track elements
				GridElement geTop = mapGrid.getGridElement(mapCoord.getX(), mapCoord.getY()+1);
				GridElement geRi = mapGrid.getGridElement(mapCoord.getX()+1, mapCoord.getY());
				GridElement geBot = mapGrid.getGridElement(mapCoord.getX(), mapCoord.getY()-1);
				GridElement geLe = mapGrid.getGridElement(mapCoord.getX()-1, mapCoord.getY());
				
				boolean top = true;
				boolean left = true;
				boolean right = true;
				boolean bottom = true;
				
				if(geTop.hasTrackPiece()) {
					if(buildRoad.containsCoordinate(geTop.getCoordinate())) {
						top = true;
					} else {
						top = false;
					}
				}
				if(geRi.hasTrackPiece()) {
					if(buildRoad.containsCoordinate(geRi.getCoordinate())) {
						right = true;
					} else {
						right = false;
					}
				}
				if(geBot.hasTrackPiece()) {
					if(buildRoad.containsCoordinate(geBot.getCoordinate())) {
						bottom = true;
					} else {
						bottom = false;
					}
				}
				if(geLe.hasTrackPiece()) {
					if(buildRoad.containsCoordinate(geLe.getCoordinate())) {
						left = true;
					} else {
						left = false;
					}
				}


				//Only the track elements that do not border on any other external track element,
				//which means not containing to this track.
				if(top && right && bottom && left) {				
					if(redColorOL.isContained(ball)) {
						redColorOL.removeSpatial(ball);
					}
					buildRoad.addUpdateField(mapCoord);
				} else {
					redColorOL.addSpatial(ball);
				}
			}
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}        
	}
	
	private void mouseRemoveRoadElement(int x, int y) {
    	Vector2f screenPos = new Vector2f();
    	//Get the position that the mouse is pointing to
		screenPos.set(x, y);
		// Get the world location of that X,Y value
		Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
		// Create a ray starting from the camera, and going in the direction
        // of the mouse's location
        final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
                .subtractLocal(cam.getLocation()));
        mouseRay.getDirection().normalizeLocal();
        //Calculate terrain intersection and set ball translation
        picker.getTerrainIntersection(mouseRay, ball.getLocalTranslation());
        Coordinate mapCoord = mapGrid.getGridIndex(ball.getWorldTranslation());
        try {
			GridElement ge = mapGrid.getGridElement(mapCoord.getX(), mapCoord.getY());
			if(!ge.isEmpty()) {
				if(buildRoad.containsCoordinate(ge.getCoordinate())) {				
					buildRoad.removeUpdateField(mapCoord);
				}
			}
		} catch (MapElementIndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}        
	}	
	
	
	
	
	
	
	
	public void onButton(int button, boolean pressed, int x, int y) {
		if(mouseInputState.isVEHICLE_SELECTOR()) {
			// VehicleSelector is active, but only if the left mouse button was clicked
			if(button==0 && pressed ==false) {
				// TODO this is not final? >Not a vehicle pick
				processPick(x,y);
			}	
		}
		if(mouseInputState.isTRACK_INSTALLER()) {
			// TrackInstaller is active, but only if the left mouse button was clicked
			if(button==0 && pressed ==false) {
				// TODO this is not final
				mouseNewRoadElement(x,y);
			}
			// TrackInstaller is active, but only if the right mouse button was clicked
			if(button==1 && pressed ==false) {
				// TODO this is not final
				mouseRemoveRoadElement(x,y);
			}

		}
	}

	public void onMove(int xDelta, int yDelta, int newX, int newY) {
		if(mouseInputState.isEMPTY_DEFAULT()) {
			// Nothing to do here
		}
		if (mouseInputState.isTRACK_INSTALLER()) {
			mouseProcessNewRoadElementMode(newX, newY);
		}		
	}

	public void onWheel(int wheelDelta, int x, int y) {
		// TODO Auto-generated method stub
		
	}
}
